using System;
using System.Collections.Generic;
using Gameplay.PVE.Data;
using Gameplay.PVE.Utils;
using UnityEditor;
using UnityEngine;
using Yoozoo.Framework.Managers;

namespace Gameplay.PVE.Editor
{
    public class PveMapEditorWindow : EditorWindow
    {
        public static PveMapData data;
        private static PveMapEditorWindow Instance;
        

        public PveMapEditorWindow()
        {
            Instance = this;
        }
        [MenuItem("GTATools/GamePlay/PVE/MapEditor")]
        public static void Init()
        {
            var window = EditorWindow.GetWindow<PveMapEditorWindow>("挂机编辑器", true);
            Instance.Initialize();
            EditorApplication.update += Instance.Update;
        }

        private bool isEditingBlocks;
        private Camera camera;
        private float lastWheelTime;
        public void Update()
        {
            if (isEditingBlocks)
            {
                if (camera == null)
                {
                    var cameraObj = GameObject.Find("Camera");
                    camera = cameraObj.GetComponent<Camera>();
                }

                if (lastWheelTime != 0 && TimeManager.logicTime - lastWheelTime > 0.2f)
                {
                    lastWheelTime = 0;
                }
                if (lastWheelTime == 0)
                {
                    var wheel = Input.GetAxis("Mouse ScrollWheel");
                    if (wheel > 0)
                    {
                        mapEditorBrushRange += 1;
                        lastWheelTime = TimeManager.logicTime;
                    }
                    else if (wheel < 0)
                    {
                        mapEditorBrushRange -= 1;
                        lastWheelTime = TimeManager.logicTime;
                    }
                }
                
                var center = Input.mousePosition;
                var leftBottomPos = data.blocksOffset;
                var rightTopPos = leftBottomPos + new Vector3(mapWidth,0,mapHeight);
                var x = leftBottomPos.x + mapWidth * center.x / 1334f;
                var y = leftBottomPos.z + mapHeight * center.y / 750f;
                mapEditorBrush.transform.position = new Vector3(x,1,y);
                mapEditorBrush.transform.localScale = new Vector3(mapEditorBrushRange / 10f,0.01f,mapEditorBrushRange / 10f);
                bool isAdd = Input.GetMouseButton(0);
                bool isDel = Input.GetMouseButton(1);
                if (!isAdd && !isDel)
                {
                    return;
                }
                //if (Input.GetMouseButton(0))
                {
                  
                    int centerX = (int) (center.x / 1334 * grids.GetUpperBound(0));
                    int centerY = (int)(center.y / 750 * grids.GetUpperBound(1));
                    
                    for (int i = centerX - mapEditorBrushRange; i <= centerX + mapEditorBrushRange; i++)
                    {
                        for (int j = centerY - mapEditorBrushRange; j <= centerY + mapEditorBrushRange; j++)
                        {
                            if (i < 0 || j < 0 || i >= grids.GetUpperBound(0) || j >= grids.GetUpperBound(1))
                            {
                                
                            }
                            else
                            {
                                data.blocks[i * data.height + j] = isAdd;
                                UpdateBlock(i,j,isAdd);
                            }
                        }
                    }
                }
            }
        }
        
        private void OnDestroy()
        {
            if (root != null)
            {
                GameObject.DestroyImmediate(root.gameObject);
            }
            root = null;
            EditorApplication.update -= Instance.Update;
        }

        private void Initialize()
        {
            Instance.LoadMapData(1);
            Reload();
        }
        
        private Vector2 scrollPos;
        private string mapId = "1";
        
        private Transform root;
        private Transform astarRoot;
        private Node[,] grids;

        private float mapWidth;
        private float mapHeight;
        
        private class Node
        {
            public Vector3 position;
            public bool isBlock;
            public GameObject obj;
        }
        
        private void Reload()
        {
            if (root != null)
            {
                GameObject.DestroyImmediate(root.gameObject);
            }

            root = new GameObject("[Root]").transform;
            for (int i = 0; i < data.regions.Count; i++)
            {
                AddRegion(data.regions[i],data.regions[i].id);
            }

            for (int i = 0; i < data.rpgBattleRegions.Count; i++)
            {
                AddRpgBattleRegion(data.rpgBattleRegions[i],data.rpgBattleRegions[i].id);
            }

            for (int i = 0; i < data.points.Count; i++)
            {
                AddMapLoadPoint(data.points[i].index,data.points[i].position,data.points[i].direction,data.points[i].nextMapOffset,data.points[i].mapList);
            }

            for (int i = 0; i < data.peoplePoint.Count; i++)
            {
                AddPeoplePoint(i, data.peoplePoint[i]);
            }
            
            astarRoot = new GameObject("[AStarRoot]").transform;
            astarRoot.transform.SetParent(root);
            var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(
                "Assets/ResourcesAssets/Pve/Prefabs/Others/astarNode.prefab");

            var mainCameraObj = GameObject.Find("Camera");//.GetComponent<Camera>();
            if (mainCameraObj == null)
            {
                return;
            }
            var mainCamera = mainCameraObj.GetComponent<Camera>();
            mapHeight = mainCamera.orthographicSize * 2;
            mapWidth = mapHeight / 750 * 1334;
            int mapW = (int)(mapWidth / AStarMgr.gridSize.x);
            int mapH = (int) (mapHeight / AStarMgr.gridSize.y);
            if (data.blocks == null || data.blocks.Count < mapH * mapW)
            {
                data.blocks = new List<bool>();
                for (int i = 0; i < mapW; i++)
                {
                    //var list = new List<bool>();
                    for (int j = 0; j < mapH; j++)
                    {
                        data.blocks.Add(false);
                    }
                    //data.blocks.Add(list);
                }

                data.width = mapW;
                data.height = mapH;
            }
            grids = new Node[mapW,mapH];
            Vector3 offset = new Vector3(mainCamera.transform.position.x, 0, mainCamera.transform.position.z);
            data.blocksOffset = offset - new Vector3(mapW / 2f,0,mapH / 2f) * AStarMgr.gridSize.x;
            for (int i = 0; i < mapW; i++)
            {
                for (int j = 0; j < mapH; j++)
                {
                    var node = new Node
                    {
                        isBlock = false,
                        obj = null,
                        position = new Vector3((i) * AStarMgr.gridSize.x,0.1f,(j) * AStarMgr.gridSize.y) - new Vector3(mapW / 2f,0,mapH / 2f) * AStarMgr.gridSize.x + offset,
                    };
                    grids[i, j] = node;
                    int index = i * mapH + j;
                    UpdateBlock(i, j, data.blocks[index]);
                }
            }
        }


        private void UpdateBlock(int x,int y,bool isBlock)
        {
            var node = grids[x, y];
            if (isBlock)
            {
                if (node.obj == null)
                {
                    node.obj = GameObject.CreatePrimitive(PrimitiveType.Plane);
                    node.obj.transform.SetParent(astarRoot);
                    node.obj.transform.localScale = new Vector3(AStarMgr.gridSize.x / 10 * 0.9f, 0, AStarMgr.gridSize.y / 10 * 0.9f);
                    node.obj.transform.localPosition = node.position + new Vector3(0,20,0);
                }
            }
            else
            {
                if (node.obj != null)
                {
                    GameObject.Destroy(node.obj);
                    node.obj = null;
                }
            }
        }

        private void AddRpgBattleRegion(RpgBattleRegion region, int i)
        {
            var regionRoot = new GameObject("RpgBattleRegion" + i);
            regionRoot.transform.SetParent(root);
            var attr = regionRoot.AddComponent<RpgRegionAttribute>();
            if (region != null)
            {
                regionRoot.transform.position = region.battlePosition;
                attr.Init(i, region);
            }
            else
            {
                regionRoot.transform.position = Vector3.zero;
                attr.Init(i);
            }
        }
        
        private void AddRegion(PveMapRegion region,int i)
        {
            var regionRoot = new GameObject("region" + i);
            regionRoot.transform.SetParent(root);
            var attr = regionRoot.AddComponent<RegionAttribute>();
            if (region != null)
            {
                regionRoot.transform.position = region.position;
                attr.Init(i, region);
                
            }
            else
            {
                regionRoot.transform.position = Vector3.zero;
                attr.Init(i);
            }
        }

        private void AddMapLoadPoint(int index, Vector3 position, Vector3 direction,float nextMapOffset = 0,List<int> segments = null)
        {
            var point = new GameObject("point" + index);
            point.transform.SetParent(root);
            point.transform.position = position;
            point.transform.forward = direction;
            var attr = point.AddComponent<MapPointAttribute>();
            attr.index = index;
            attr.showMapSegments = new List<int>();
            attr.nextMapOffset = nextMapOffset;
            if (segments != null)
            {
                attr.showMapSegments.AddRange(segments);
            }
            
        }

        private void AddPeoplePoint(int index, Vector3 position)
        {
            var point = new GameObject("peoplePoint" + index);
            point.transform.SetParent(root);
            point.transform.position = position;
            point.AddComponent<PeoplePointAttribute>();

        }
        private GameObject mapEditorBrush;
        private int mapEditorBrushRange = 3;
        
        private void OnGUI()
        {
            EditorGUILayout.BeginHorizontal();
            scrollPos =
                EditorGUILayout.BeginScrollView(scrollPos, false, false);
            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("地图id:");
            mapId = EditorGUILayout.TextField(mapId);
           
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Space();
            if (GUILayout.Button("读取"))
            {
                int mapId;
                int.TryParse(this.mapId, out mapId);
                LoadMapData(mapId);
                Reload();
            }
            
           
            EditorGUILayout.Space();
            if (GUILayout.Button("添加区域"))
            {
                var regions = FindObjectsOfType<RegionAttribute>();
                AddRegion(null,regions.Length);
            }
            
            if (GUILayout.Button("添加Rpg战斗区域"))
            {
                var regions = FindObjectsOfType<RpgRegionAttribute>();
                AddRpgBattleRegion(null,regions.Length);
            }

            if (isEditingBlocks)
            {
                if (GUILayout.Button("结束编辑,分辨率1334x750"))
                {
                    isEditingBlocks = false;
                    GameObject.DestroyImmediate(mapEditorBrush);
                    mapEditorBrush = null;
                }
            }
            else
            {
                if (GUILayout.Button("编辑阻挡,分辨率1334x750"))
                {
                    isEditingBlocks = true;
                    mapEditorBrush = GameObject.CreatePrimitive(PrimitiveType.Plane);
                    mapEditorBrush.transform.SetParent(root);
                    mapEditorBrush.transform.localScale = new Vector3(mapEditorBrushRange / 5,0,mapEditorBrushRange / 5);
                }
            }
            EditorGUILayout.Space();
            if (GUILayout.Button("添加地图加载点"))
            {
                var points = FindObjectsOfType<MapPointAttribute>();
                AddMapLoadPoint(points.Length,Vector3.zero,Vector3.forward);
            }

            if (GUILayout.Button("添加行人出生点"))
            {
                var peoplePoints = FindObjectsOfType<PeoplePointAttribute>();
                AddPeoplePoint(peoplePoints.Length,Vector3.zero);
            }

            if (GUILayout.Button("保存"))
            {
                int mapId;
                int.TryParse(this.mapId, out mapId);
                data.mapId = mapId;
                data.regions = new List<PveMapRegion>();
                data.rpgBattleRegions = new List<RpgBattleRegion>();
                data.points = new List<PveMapPoint>();
                data.peoplePoint = new List<Vector3>();
                var regions = FindObjectsOfType<RegionAttribute>();
                for (int i = 0; i < regions.Length; i++)
                {
                    regions[i].SaveRegion();
                    var region = regions[i].region;
                    data.regions.Add(region);
                }
                data.regions.Sort((a,b)=>a.id.CompareTo(b.id));

                var battleRegions = FindObjectsOfType<RpgRegionAttribute>();
                for (int i = 0; i < battleRegions.Length; i++)
                {
                    battleRegions[i].SaveRegion();
                    var region = battleRegions[i].region;
                    data.rpgBattleRegions.Add(region);
                }
                data.rpgBattleRegions.Sort((a,b)=>a.id.CompareTo(b.id));
                var points = FindObjectsOfType<MapPointAttribute>();
                for (int i = 0; i < points.Length; i++)
                {
                    var point = new PveMapPoint
                    {
                        index = points[i].index,
                        position = points[i].gameObject.transform.position,
                        direction = points[i].gameObject.transform.forward,
                        mapList = new List<int>(),
                        nextMapOffset = points[i].nextMapOffset,
                    };
                    point.mapList.AddRange(points[i].showMapSegments);
                    data.points.Add(point);
                }

                data.points.Sort((a,b)=> a.index.CompareTo(b.index));

;
                var peoplePoints = FindObjectsOfType<PeoplePointAttribute>();
                for (int i = 0; i < peoplePoints.Length; i++)
                {
                    data.peoplePoint.Add(peoplePoints[i].transform.position);
                }

                EditorUtility.SetDirty(data);
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
                EditorUtility.SetDirty(data);
                EditorUtility.DisplayDialog("通知", "保存成功", "OK");

            }
            EditorGUILayout.EndScrollView();
            EditorGUILayout.EndHorizontal();
        }
        
        private void LoadMapData(int index)
        {
            string path = string.Format("Assets/ResourcesAssets/Pve/Data/PveMap{0}.asset", index);
            data = AssetDatabase.LoadAssetAtPath<ScriptableObject>(path) as PveMapData;
            if (data == null)
            {
                data = ScriptableObject.CreateInstance<PveMapData>();
                AssetDatabase.CreateAsset(data, path);
            }
        }

    }
}